package com.me.myFramework.aop22.aop122.intercept.method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 《AOP-122》：  <br><br>
 *
 * TODO MethodBeforeAdviceInterceptor 中直接反射调用了目标方法，无法实现链式调用。需要抽取一个执行器：<br>
 *  1，如果当前节点是责任链的最后一个节点，直接调用目标方法；
 *  2，如果当前节点不是责任链的最后一个节点，需要进行链式调用。<br><br>
 *
 *  不同 MethodInterceptor（增强执行器）中 Advice（增强逻辑）所需要的参数不一致（后置增强需要返回值，前置增强不需要）， 如何进行链式调用呢？
 *  把所有参数（目标对象、代理对象、目标方法、方法参数）
 */
public class ReflectiveMethodInvocation122 implements MethodInvocation {

    /** 代理对象 */
    private Object proxy;
    /** 目标对象 */
    private Object target;
    /** 要执行的目标方法 */
    private Method method;
    /** 目标方法的入参 */
    private Object[] args = new Object[0];
    /** 目标对象的类信息 */
    private final Class<?> targetClass;

    /** 负责执行增强的拦截器，也就是前置增强、后置增强的模板方法 */
    private List<MethodInterceptor> interceptors;

    /**
     * 拦截器的下标，用来指示即将执行的拦截器。初始值为 -1
     */
    private int currentInterceptorIndex = -1;

    public ReflectiveMethodInvocation122(Object proxy, Object target, Method method, Object[] args, Class<?> targetClass, List<MethodInterceptor> interceptors) {
        this.proxy = proxy;
        this.target = target;
        this.method = method;
        this.args = args;
        this.targetClass = targetClass;
        this.interceptors = interceptors;
    }

    @Override
    public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
            return this.getMethod().invoke(this.getThis(), this.getArguments());
        }
        else {
            return this.interceptors.get(++this.currentInterceptorIndex).invoke(this);
        }
    }

    @Override
    public Object getThis() { return this.target; }

    @Override
    public Method getMethod() { return this.method; }

    @Override
    public Object[] getArguments() { return this.args; }

    @Override
    public AccessibleObject getStaticPart() {
        return null;
    }

    /** 获取 List<MethodInterceptor> 的节点数 */
    public int getInterceptorSize() {
        return this.interceptors.size();
    }

    /**
     * 下一个 MethodInterceptor
     */
    public MethodInterceptor getNextInterceptor() {
        return this.interceptors.get(++this.currentInterceptorIndex);
    }

    /**
     * 获取当前 MethodInterceptor 在责任链中的下标
     *
     * @return 下标
     */
    public int getCurrentIndex() {
        return this.currentInterceptorIndex;
    }

}
